#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "circle.h"
#include "bmpheader.h"

static void _circ_covert_rgb_to_yuv (struct circle *circ)
{
}

static int _circ_draw_into_pixel_arry_image_file (struct circle *circ)
{
	int ret =-1;
	FILE *fp = NULL;
	int row =0, col=0;
	unsigned char * buf = circ->buffer;

	fp = fopen (circ->file, "w+");

	if (fp != NULL) {
		for (row =0;row<circ->y_res;row++) {
			for (col =0;col<circ->x_res;col++) {
	       			fwrite(buf, 1, 1,fp);
	       			fwrite(buf+1, 1, 1,fp);
	       			fwrite(buf+2, 1, 1,fp);
				buf +=4;
			}
		}
		fclose (fp);
		ret = 0;
	} else {
		perror ("fopen:");
	}
	return ret;	
}

static int _circ_draw_into_bmp_image_file (struct circle *circ, struct bmp_header *bmp)
{
        int ret =-1;
        FILE *fp = NULL;
        int row =0, col=0;
        unsigned char *buf = circ->buffer;

        fp = fopen (circ->file, "w+");

        if (fp != NULL) {
		// Write BMP header here first to file then pixel array
		fwrite(&bmp->signiture, 1, 2,fp);
		fwrite(&bmp->size, 1, 4,fp);
                fwrite(&bmp->reserved1, 1, 2,fp);
                fwrite(&bmp->reserved2, 1, 2,fp);
                fwrite(&bmp->pixel_arry, 1, 4, fp);
                fwrite(&bmp->bmpheader_size, 1, 4,fp);
                fwrite(&bmp->width, 1, 4, fp);
                fwrite(&bmp->height,1,4,fp);
                fwrite(&bmp->planes,1,2,fp);
                fwrite(&bmp->bpps,1,2,fp);
                fwrite(&bmp->compression,1,4,fp);
                fwrite(&bmp->fsize, 1,4,fp);
                fwrite(&bmp->h_res, 1,4,fp);
                fwrite(&bmp->w_res, 1,4,fp);
                fwrite(&bmp->ncolor, 1,4,fp);
                fwrite(&bmp->nimpcolor,1,4,fp);

                for (row =0;row<circ->y_res;row++) {
                        for (col =0;col<circ->x_res;col++) {
                                fwrite(buf, 1, 1,fp);
                                fwrite(buf+1, 1, 1,fp);
                                fwrite(buf+2, 1, 1,fp);
                                buf +=4;
                        }
                }
                fclose (fp);
                ret = 0;
        } else {
                perror ("fopen:");
        }
        return ret;
}

static unsigned char * _circ_allocate_pixel_arry(struct circle *circ)
{
	if (circ != NULL)
		return (unsigned char *) malloc (circ->x_res*circ->y_res*4);
	else
		return NULL;
}

static int _circ_draw_circle(struct circle *circ)
{
	unsigned char *buf = circ->buffer;
	int angle = 0, x, y;

	for (angle=0;angle<=360;angle++) {
		x = circ->x + circ->radii*cos(angle);
		y = circ->y + circ->radii*sin(angle);

		printf ("%d %d\r\n",x,y);		
		buf = circ->buffer + (y*4*circ->x_res) + x*4;
		*buf     = (unsigned char)(0x000000FF & circ->line_color >> 16);
		*(buf+1) = (unsigned char)(0x000000FF & circ->line_color >> 8);
		*(buf+2) = (unsigned char)(0x000000FF & circ->line_color);
	}
}

static int _circ_fill_background_plane(struct circle *circ)
{
	int ret = -1;
        int row =0, col=0;
	unsigned char *buf = circ->buffer;

	if (circ == NULL)
		return ret;

	if (circ->buffer == NULL)
		return ret;
	

	printf ("RGB[%x]: %x %x %x \r\n",circ->line_color,
		(unsigned char)(0x000000FF & circ->line_color >> 16),
		(unsigned char)(0x000000FF & circ->line_color >> 8),
		(unsigned char)(0x000000FF & circ->line_color));

	printf ("RGB[%x]: %x %x %x \r\n",circ->bg_color,
		(unsigned char)(0x000000FF & circ->bg_color >> 16),
		(unsigned char)(0x000000FF & circ->bg_color >> 8),
		(unsigned char)(0x000000FF & circ->bg_color));
        for (row = 0; row <circ->y_res;row++) {
                for (col =0;col<circ->x_res;col++) {
			*buf     = (unsigned char)(0x000000FF & circ->bg_color >> 16);
			*(buf+1) = (unsigned char)(0x000000FF & circ->bg_color >> 8);
			*(buf+2) = (unsigned char)(0x000000FF & circ->bg_color);
			*(buf+3) = 0x00;
			buf += 4;
		}
	}

	_circ_draw_circle (circ);

	return 0;
}

int draw_circle_to_console(struct circle *circ)
{
	int ret = -1;
        int row =0, col=0;
        int tst =0;
        char buf[20];
	unsigned char *pixel_arry = _circ_allocate_pixel_arry(circ);
	
	if (pixel_arry != NULL) {
		circ->buffer = pixel_arry;
		/* Fill the Background color of plane and draw circle with line color */
		ret = _circ_fill_background_plane(circ);
	} else {
		return ret;
	}

        for (row = 0; row <circ->y_res;row++) {
                for (col =0;col<circ->x_res;col++) {
			if (*pixel_arry     == (unsigned char)(0x000000FF & circ->line_color >> 16) && 
			    *(pixel_arry+1) == (unsigned char)(0x000000FF & circ->line_color >> 8) && 
			    *(pixel_arry+2) == (unsigned char)(0x000000FF & circ->line_color))
                        {
				 sprintf (buf, "#");
                        }
			else
				sprintf (buf, ".");
			
			if (tst == 4) {
				tst = 0;
				printf ("%s",buf);
			} else
				tst++;
			pixel_arry += 4;
                }
		printf ("\r\n");
        }
	return ret;
}

int draw_circle_raw_yuv_image_file(struct circle *circ)
{
	int ret = -1;
	unsigned char *pixel_arry = _circ_allocate_pixel_arry(circ);
	
	if (pixel_arry != NULL) {
		circ->buffer = pixel_arry;

		/* Fill the Background color of plane and draw circle with line color */
		ret = _circ_fill_background_plane(circ);

		/* Convert the RGB pixel array to yuv based on provided format of yuv */
		_circ_covert_rgb_to_yuv(circ);

		/* Write the circle to file */
		ret = _circ_draw_into_pixel_arry_image_file(circ);

		free (pixel_arry);
		circ->buffer = NULL;

		if (ret != 0)
			printf ("%s: Failed to write image\r\n",__func__);
		else
			printf ("%s: Success\r\n",__func__);
	} else 
		printf ("%s: Failed no memory\r\n",__func__);
	return ret;
}

int draw_circle_raw_rgb_image_file(struct circle *circ)
{
	int ret = -1;
	unsigned char *pixel_arry = _circ_allocate_pixel_arry(circ);
	
	if (pixel_arry != NULL) {
		circ->buffer = pixel_arry;

		/* Fill the Background color of plane and draw circle with line color */
		ret = _circ_fill_background_plane(circ);

		/* Write the circle to file */
		ret = _circ_draw_into_pixel_arry_image_file(circ);

		free (pixel_arry);
		circ->buffer = NULL;

		if (ret != 0)
			printf ("%s: Failed to write RGB image\r\n",__func__);
		else
			printf ("%s: Success\r\n",__func__);
	} else 
		printf ("%s: Failed no memory\r\n",__func__);
	return ret;
}

int draw_circle_bmp_image_file(struct circle *circ)
{
	int ret = -1;
	struct bmp_header bmp;
	unsigned char *pixel_arry = _circ_allocate_pixel_arry(circ);
	
	if (pixel_arry != NULL) {
		circ->buffer = pixel_arry;

		/* Fill the Background color of plane and draw circle with line color */
		ret = _circ_fill_background_plane(circ);

	        bmp.signiture 		= 0x4d42;
	        bmp.size 		= sizeof (struct bmp_header) + (circ->x_res*circ->y_res*3);
        	bmp.reserved1 		= 0; 
        	bmp.reserved2 		= 0;
        	bmp.pixel_arry 		= sizeof (struct bmp_header);
        	bmp.bmpheader_size 	= 40;
        	bmp.width 		= circ->x_res;
        	bmp.height 		= circ->y_res;
        	bmp.planes 		= 1;
        	bmp.bpps        	= 24;
        	bmp.compression 	= 0;
        	bmp.fsize       	= (circ->x_res*circ->y_res*3);
        	bmp.h_res       	= 0x0b13;  //circ->x_res;
        	bmp.w_res       	= 0x0b13; //circ->y_res;
		bmp.ncolor      	= 0;
		bmp.nimpcolor   	= 0;

		/* Write the circle to file */
		ret = _circ_draw_into_bmp_image_file(circ, &bmp);

		free (pixel_arry);
		circ->buffer = NULL;

		if (ret != 0)
			printf ("%s: Failed to write \r\n",__func__);
		else
			printf ("%s: Success\r\n",__func__);
	} else 
		printf ("%s: Failed no memory\r\n",__func__);
	return ret;
}

int draw_circle_jpg_image_file(struct circle *circ)
{
	int ret = -1;
	return ret;
}

int draw_circle_rgb_buffer(struct circle *circ)
{
	int ret = -1;
	unsigned char *pixel_arry = _circ_allocate_pixel_arry(circ);
	
	if (pixel_arry != NULL) {
		circ->buffer = pixel_arry;

		/* Fill the Background color of plane and draw circle with line color */
		ret = _circ_fill_background_plane(circ);

		if (ret != 0)
			printf ("%s: Failed to write \r\n",__func__);
		else
			printf ("%s: Success\r\n",__func__);
	} else 
		printf ("%s: Failed no memory\r\n",__func__);
	return ret;
}
